using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Volo.Abp.BackgroundWorkers;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Threading;
using Volo.Abp.Uow;
using TenantManagementService.Monitoring;

namespace TenantManagementService.Monitoring
{
    /// <summary>
    /// 告警规则评估后台服务
    /// </summary>
    public class AlertRuleEvaluationService : AsyncPeriodicBackgroundWorkerBase
    {
        private readonly IServiceProvider _serviceProvider;
        private readonly ILogger<AlertRuleEvaluationService> _logger;

        public AlertRuleEvaluationService(
            AbpAsyncTimer timer,
            IServiceProvider serviceProvider,
            ILogger<AlertRuleEvaluationService> logger) : base(timer)
        {
            _serviceProvider = serviceProvider;
            _logger = logger;
            Timer.Period = 30000; // 30秒检查一次
        }

        protected override async Task DoWorkAsync(PeriodicBackgroundWorkerContext workerContext)
        {
            try
            {
                _logger.LogDebug("开始执行告警规则评估检查");

                using var scope = _serviceProvider.CreateScope();
                var monitoringService = scope.ServiceProvider.GetRequiredService<IMonitoringService>();

                await monitoringService.CheckAlertRulesAsync();

                _logger.LogDebug("告警规则评估检查完成");
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "告警规则评估检查失败");
            }
        }
    }

    /// <summary>
    /// 告警规则引擎
    /// </summary>
    public class AlertRuleEngine : ITransientDependency
    {
        private readonly IRepository<AlertRule, Guid> _alertRuleRepository;
        private readonly IRepository<MonitoringMetricValue, Guid> _metricValueRepository;
        private readonly IRepository<Alert, Guid> _alertRepository;
        private readonly ILogger<AlertRuleEngine> _logger;

        public AlertRuleEngine(
            IRepository<AlertRule, Guid> alertRuleRepository,
            IRepository<MonitoringMetricValue, Guid> metricValueRepository,
            IRepository<Alert, Guid> alertRepository,
            ILogger<AlertRuleEngine> logger)
        {
            _alertRuleRepository = alertRuleRepository;
            _metricValueRepository = metricValueRepository;
            _alertRepository = alertRepository;
            _logger = logger;
        }

        /// <summary>
        /// 评估所有启用的告警规则
        /// </summary>
        public async Task<List<Alert>> EvaluateAllRulesAsync(CancellationToken cancellationToken = default)
        {
            var triggeredAlerts = new List<Alert>();

            try
            {
                var activeRules = await _alertRuleRepository.GetListAsync(r => r.IsEnabled, cancellationToken: cancellationToken);

                _logger.LogDebug("开始评估 {Count} 个告警规则", activeRules.Count);

                foreach (var rule in activeRules)
                {
                    try
                    {
                        var alert = await EvaluateRuleAsync(rule, cancellationToken);
                        if (alert != null)
                        {
                            triggeredAlerts.Add(alert);
                        }
                    }
                    catch (Exception ex)
                    {
                        _logger.LogError(ex, "评估告警规则 {RuleName} 失败", rule.DisplayName);
                    }
                }

                _logger.LogInformation("告警规则评估完成，触发 {Count} 个新告警", triggeredAlerts.Count);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "评估告警规则失败");
            }

            return triggeredAlerts;
        }

        /// <summary>
        /// 评估单个告警规则
        /// </summary>
        public async Task<Alert?> EvaluateRuleAsync(AlertRule rule, CancellationToken cancellationToken = default)
        {
            // 检查是否已经存在活跃的告警
            var existingActiveAlert = await _alertRepository.FirstOrDefaultAsync(a =>
                a.AlertRuleId == rule.Id && a.Status == AlertStatus.Active, cancellationToken: cancellationToken);

            var shouldTrigger = await ShouldTriggerAlertAsync(rule, cancellationToken);

            if (shouldTrigger && existingActiveAlert == null)
            {
                // 创建新告警
                return await CreateAlertAsync(rule, cancellationToken);
            }
            else if (!shouldTrigger && existingActiveAlert != null)
            {
                // 自动解决告警
                await ResolveAlertAsync(existingActiveAlert, cancellationToken);
            }

            return null;
        }

        /// <summary>
        /// 检查是否应该触发告警
        /// </summary>
        private async Task<bool> ShouldTriggerAlertAsync(AlertRule rule, CancellationToken cancellationToken)
        {
            try
            {
                // 获取最近一段时间的指标数据
                var endTime = DateTime.Now;
                var startTime = endTime.AddSeconds(-rule.Duration);

                var queryable = await _metricValueRepository.GetQueryableAsync();

                queryable = queryable.Where(v => v.Metric.Name == rule.MetricName && v.TenantId == rule.TenantId)
                                      .Where(v => v.Timestamp >= startTime && v.Timestamp <= endTime);

                // 应用标签过滤器
                var labelFilters = rule.GetLabelFilters();
                if (labelFilters != null)
                {
                    foreach (var filter in labelFilters)
                    {
                        queryable = queryable.Where(v => v.Dimensions != null && v.Dimensions.Contains($"\"{filter.Key}\":\"{filter.Value}\""));
                    }
                }

                var metricValues = await AsyncExecuter.ToListAsync(queryable, cancellationToken);

                if (metricValues.Count == 0)
                {
                    return false;
                }

                // 根据规则类型判断是否触发告警
                return rule.Operator.ToLower() switch
                {
                    "gt" => metricValues.Any(v => v.Value > rule.Threshold),
                    "gte" => metricValues.All(v => v.Value >= rule.Threshold),
                    "lt" => metricValues.Any(v => v.Value < rule.Threshold),
                    "lte" => metricValues.All(v => v.Value <= rule.Threshold),
                    "eq" => metricValues.All(v => v.Value == rule.Threshold),
                    "ne" => metricValues.Any(v => v.Value != rule.Threshold),
                    "avg_gt" => metricValues.Average(v => v.Value) > rule.Threshold,
                    "avg_lt" => metricValues.Average(v => v.Value) < rule.Threshold,
                    "max_gt" => metricValues.Max(v => v.Value) > rule.Threshold,
                    "min_lt" => metricValues.Min(v => v.Value) < rule.Threshold,
                    _ => false
                };
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "检查告警规则 {RuleName} 是否应该触发时失败", rule.DisplayName);
                return false;
            }
        }

        /// <summary>
        /// 创建告警
        /// </summary>
        private async Task<Alert> CreateAlertAsync(AlertRule rule, CancellationToken cancellationToken)
        {
            try
            {
                // 获取当前指标值
                var currentValue = await GetLatestMetricValueAsync(rule.MetricName, rule.GetLabelFilters(), rule.TenantId, cancellationToken);

                var alert = new Alert(
                    Guid.NewGuid(),
                    rule.Id,
                    rule.Level,
                    rule.DisplayName,
                    $"指标 '{rule.MetricName}' 触发了告警规则，当前值: {currentValue}",
                    currentValue ?? 0m,
                    rule.GetLabelFilters(),
                    rule.TenantId
                );

                await _alertRepository.InsertAsync(alert, autoSave: true, cancellationToken: cancellationToken);

                // 更新规则的触发统计
                rule.TriggerAlert(currentValue ?? 0m, rule.GetLabelFilters());
                await _alertRuleRepository.UpdateAsync(rule, autoSave: true, cancellationToken: cancellationToken);

                _logger.LogWarning("告警已创建: {AlertTitle} - 规则: {RuleName} - 当前值: {Value}",
                    alert.Title, rule.DisplayName, currentValue);

                return alert;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "创建告警失败，规则: {RuleName}", rule.DisplayName);
                throw;
            }
        }

        /// <summary>
        /// 解决告警
        /// </summary>
        private async Task ResolveAlertAsync(Alert alert, CancellationToken cancellationToken)
        {
            try
            {
                alert.Resolve("条件已恢复正常");
                await _alertRepository.UpdateAsync(alert, autoSave: true, cancellationToken: cancellationToken);

                _logger.LogInformation("告警已自动解决: {AlertTitle}", alert.Title);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "自动解决告警失败: {AlertTitle}", alert.Title);
            }
        }

        /// <summary>
        /// 获取最新的指标值
        /// </summary>
        private async Task<decimal?> GetLatestMetricValueAsync(string metricName, Dictionary<string, string>? dimensions, Guid? tenantId, CancellationToken cancellationToken)
        {
            try
            {
                var queryable = await _metricValueRepository.GetQueryableAsync();

                queryable = queryable.Where(v => v.Metric.Name == metricName && v.TenantId == tenantId)
                                      .OrderByDescending(v => v.Timestamp)
                                      .Take(1);

                // 应用标签过滤器
                if (dimensions != null)
                {
                    foreach (var filter in dimensions)
                    {
                        queryable = queryable.Where(v => v.Dimensions != null && v.Dimensions.Contains($"\"{filter.Key}\":\"{filter.Value}\""));
                    }
                }

                var latestValue = await AsyncExecuter.FirstOrDefaultAsync(queryable, cancellationToken);
                return latestValue?.Value;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取指标 {MetricName} 的最新值失败", metricName);
                return null;
            }
        }
    }
}